import math
from typing import Tuple, Dict, Any
import matplotlib
import networkx as nx
import numpy as np
from matplotlib import pyplot as plt
from python.lib import json

# 设置matplotlib正常显示中文和负号
matplotlib.rcParams['font.sans-serif'] = ['SimHei']  # 用黑体显示中文
matplotlib.rcParams['axes.unicode_minus'] = False  # 正常显示负号
# # 设置 matplotlib 使用 LaTeX 渲染
# plt.rcParams['text.usetex'] = True
# plt.rcParams['text.latex.preamble'] = r'\usepackage{amsmath}'

from DHTOA1 import load_traffic_data, process_traffic_scenario, calculate_total_delay, semi_calculate_static_latency
from allocate_switches_with_es_optimized import allocate_switches_with_es_optimized, allocate_electric_with_es_optimized
from calculate_optical_delay import calculate_communication_delay
from electric_path_algo import allocate_paths, widest_path
from find_min_max_delay_path import optimize_reconfiguration, find_min_max_delay_path
from find_min_max_delay_path_optimize import classify_traffic_paths, compute_max_delay, dynamic_traffic_reconfiguration, \
    update_link_capacities
from find_min_max_delay_path_test import matrix_to_communication_pairs
from optimize import find_optimal_electric_paths, calculate_no_recon_utilization, find_recon_electric_optical_paths, \
    initialize_utilization, calculate_communication_metrics, calculate_network_metrics, calculate_communication_times
# from optimize import find_electric_path_pairs
from topo1 import build_hybrid_topology_shared_tor,visualize_topology
from switchesalgo import allocate_switches_with_es
from topo2 import build_hybrid_topology_shared_tor

print("--------------------4节点-----------------------------")
# topo1=build_hybrid_topology_shared_tor(num_tor=4)
# topo2=build_hybrid_topology_shared_tor(num_tor=8)
# topo3=build_hybrid_topology_shared_tor(num_tor=16)
# topo=build_hybrid_topology_shared_tor()

# # 读取流量数据
# with open("traffic_evolution.json",'r') as f:
#     traffic_matrices = json.load(f)
#
# for traffic_matrix in traffic_matrices["all_to_all"]:
#     if traffic_matrix["scale_factor"] == 1.0:
#         all_to_all_4 = traffic_matrix["matrix"]
#         print("all_to_all_4", all_to_all_4)
#         break
#     else:
#         print("没找到目标流量矩阵")
#
# for traffic_matrix in traffic_matrices["all_to_all_burst"]:
#     if traffic_matrix["burst_scale"] == 1.0:
#         all_to_all_4_burst = traffic_matrix["matrix"]
#         print("all_to_all_4_burst", all_to_all_4_burst)
#         break
#     else:
#         print("没找到目标流量矩阵")


# print("all_to_all_4",traffic_matrices["all_to_all"][0])
# all_to_all_4= next((entry["matrix"] for entry in traffic_matrices["all_to_all"]
#                         if entry["scale_factor"] == 1.0), None)
# print("all-to-all_4",all_to_all_4)
# all_to_all_burst_4= next((entry["matrix"] for entry in traffic_matrices["all_to_all_burst"]
#                         if entry["scale_factor"] == 1.0), None)
# print("all_to_all_burst_4",all_to_all_burst_4)
# 将输入的流量矩阵转换为字典形式并获取通信对
def maxtri_to_dict(all_to_all_4):
    all_to_all_4_matrix = np.array(all_to_all_4)
    all_to_all_4_dict = matrix_to_communication_pairs(all_to_all_4_matrix, node_prefix="ToR")
    T0_pair = matrix_to_communication_pairs(all_to_all_4_matrix, node_prefix="ToR")
    T0 = []
    for pair in T0_pair:
        T0.append(pair)
    return all_to_all_4_dict,T0

print("****************************全更新算法**************************")
def full_update_algorithm(topo1: nx.Graph,all_to_all_4,all_to_all_burst_4 : dict) -> tuple[
    float | Any, float, float | Any]:
    all_to_all_4_dict,T1 = maxtri_to_dict(all_to_all_4)
    all_to_all_burst_4_dict,T2 = maxtri_to_dict(all_to_all_burst_4)
    # 没有突发流量前的通信对的最优路径
    paths0, util0, delays0 = allocate_switches_with_es_optimized(topo1, T1, all_to_all_4_dict, tor_switches,
                                                                 optical_switches,
                                                                 k_paths=500)
    # 输出通信对的最优路径
    for pair in paths0:
        print(f"通信对 {pair} 的最优路径为 {paths0[pair]}")
    # 有突发流量前的通信对的最优路径
    paths, util, delays = allocate_switches_with_es_optimized(topo1, T2, all_to_all_burst_4_dict, tor_switches,
                                                              optical_switches,
                                                              k_paths=500)
    for pair in paths:
        print(f"通信对 {pair} 的最优路径为 {paths[pair]}")
    # topo=topo1
    # traffic_demand=all_to_all_burst_4_dict
    # 获取需要重构和不需要重构的通信对
    recon_pairs, no_recon_pairs = classify_traffic_paths(all_to_all_burst_4_dict, paths0, paths)
    for recon_pair in recon_pairs:
        print(f"需要重构的通信对: {recon_pair}")

    for no_recon_pair in no_recon_pairs:
        print(f"不需要重构的通信对: {no_recon_pair}")
    # 计算不需要重构通信对的时间延迟
    for pair in no_recon_pairs:
        if pair in delays:
            print(f"不需要重构的通信对 {pair} 的延迟为 {delays[pair]}")


    # 计算不需要重构通信对链路利用率
    existing_utilization = calculate_no_recon_utilization(G=topo1, no_recon_pairs=no_recon_pairs,current_paths=paths,
                                                 traffic_demand=all_to_all_burst_4_dict, tor_switches=tor_switches,
                                                 k_paths=500)
    print("\n=== 不需要重构的链路利用率 ===")
    for pair, rate in existing_utilization.items():
        print(f"链路 {pair}: 当前已分配的流量为={rate:.2f} Gbps")

    # 为需要重构的通信对寻找最优的电链路
    # 获取不需要重构的通信对的流量需求
    electric_path_allocations, link_utilization, recon_electric_delay_info = allocate_electric_with_es_optimized(G=topo1, T=recon_pairs, D=all_to_all_burst_4_dict,
                                                    init_util=existing_utilization,tor_switches=tor_switches,optical_switches=optical_switches, k_paths=10)
    print("\n=== 为需要重构的通信对寻找最优的电链路 ===")
    for pair, path in electric_path_allocations.items():
        print(f"通信对 {pair}: 路径 {'→'.join(path)}")
    for pair, rate in link_utilization.items():
        print(f"链路 {pair}: 当前已分配的流量={rate:.2f} Gbps")
    for pair, delay in recon_electric_delay_info.items():
        status = f"{delay:.2f}s" if delay not in [None, float('inf')] else "超时/未分配"
        print(f"通信对 {pair}: {status}")

    recon_optical_delays=find_recon_electric_optical_paths(G=topo1, traffic_demand=all_to_all_burst_4_dict,current_paths=paths,recon_electric_delay_info=recon_electric_delay_info,recon_delay=10)
    # 合并不需要重构和需要重构的通信对延迟
    delays_1={}
    for pair in delays:
        if delays[pair] is None:
            continue
        else:
            delays_1[pair]=delays[pair]
    for pair in recon_optical_delays:
        if pair in delays:
            # delays_1[pair]=0.0
            delays_1[pair] = recon_optical_delays[pair] + 10.0
            print(f"通信对{pair}进行了重构")
            print(f"需要重构的通信对 {pair}延迟: {delays_1[pair]}")
        else:
            print(f"通信对{pair}不需要重构,通信时间为原来的")
    total_delays_1=0.0
    max_delays_1=0.0
    for pair in delays_1:
        if delays_1[pair] > max_delays_1:
            max_delays_1 = delays_1[pair]
        total_delays_1 += delays_1[pair]
    print("***********输出全更新算法的每个通信对的延迟以及所有通信对的延迟和=======================")
    for pair in delays_1:
        print(f"通信对 {pair}: {delays_1[pair]}")
    print(f"全更新路由算法的最大延迟为：{max_delays_1}")
    print(f"全更新路由算法所有通信对的延迟和为 {total_delays_1:.2f}s")
    return max_delays_1, total_delays_1,max_delays_1
# print("===================测试====================")


print("==========================半更新路由算法（只更新电链路，不更新光链路）===========================")
def semi_update_algorithm(topo1: nx.Graph,all_to_all_4,all_to_all_burst_4 : dict) -> tuple[
    dict[Any, float | Any], float, float | Any]:
    all_to_all_4_dict, T1 = maxtri_to_dict(all_to_all_4)
    all_to_all_burst_4_dict, T2 = maxtri_to_dict(all_to_all_burst_4)
    # 没有突发流量前的通信对的最优路径
    paths0, util0, delays0 = allocate_switches_with_es_optimized(topo1, T1, all_to_all_4_dict, tor_switches,
                                                                 optical_switches,
                                                                 k_paths=500)
    # 有突发流量前的通信对的最优路径
    paths, util, delays = allocate_switches_with_es_optimized(topo1, T2, all_to_all_burst_4_dict, tor_switches,
                                                              optical_switches,
                                                              k_paths=500)
    """半更新算法：仅更新电链路路径"""
    # 获取通信对中最优路径为电链路的通信对及路径
    need_recon_electric_pairs ={}
    no_need_recon_pairs0 ={}
    for pair in paths0:
        print(f"通信对 {pair}: 路径 {paths0[pair]}")
        # 遍历路径中的每一条链路
        for u, v in zip(paths0[pair], paths0[pair][1:]):
            # 如果链路类型为电链路，则更新路径
            if topo1[u][v].get('type', 'electrical') == 'electrical':
                need_recon_electric_pairs[pair] = paths0[pair]
                break
            no_need_recon_pairs0[pair]=paths0[pair]

    # print("================测试================")
    # for pair in no_need_recon_pairs0:
    #     print(f"通信对 {pair}: 路径 {no_need_recon_pairs0[pair]}")
    T_no_need_recon_pairs0=[]
    for pair in no_need_recon_pairs0:
        T_no_need_recon_pairs0.append(pair)
    print("不需要重构的通信对：")
    existing_utilization0 = calculate_no_recon_utilization(G=topo1, no_recon_pairs=T_no_need_recon_pairs0,current_paths=paths0,
                                                 traffic_demand=all_to_all_burst_4_dict, tor_switches=tor_switches,
                                                 k_paths=500)
    print("================测试================")

    for pair, rate in existing_utilization0.items():
        print(f"链路 {pair}: 当前已分配的流量为={rate:.2f} Gbps")
    print("================测试================")
    # 遍历需要重构的通信对，将他们的电链路初始化已分配的流量为0.0
    T=[]
    for pair, path in need_recon_electric_pairs.items():
    # for pair, path in paths0.items():
        print(f"通信对 {pair}: 路径 {'→'.join(path)}")
        T.append(pair)
        # 遍历路径中的每一条链路
        for u, v in zip(path, path[1:]):
            # 如果链路类型为电链路，则更新路径上已分配的流量为0.0
            if topo1[u][v].get('type') == 'electrical':
                print(f"链路 {(u, v)} 的已分配流量已重置为0.0")
                existing_utilization0[(u, v)]=0.0
                existing_utilization0[(v, u)]=0.0
            else:
                print(f"链路 {(u, v)} 的已分配流量未改变")


    # T=[]
    # for pair in  no_recon_pairs:
    #     T.append(pair)
    # # 基于不需要重构的通信对初始化每条链路上已经分配的流量
    # communication_times0, link_allocations0=calculate_communication_metrics(topo1, all_to_all_burst_4_dict, T, paths0)
    # # 如果链路在不在link_allocations0中，则初始化该链路的已分配流量为0.0,如果在则初始化为link_allocations0中对应的值
    # for edge in topo1.edges():
    #     if edge not in link_allocations0:
    #         existing_utilization[edge]=0.0
    #         existing_utilization[(edge[1],edge[0])]=0.0
    #     else:
    #         existing_utilization[edge]=link_allocations0[edge]
    #         existing_utilization[(edge[1],edge[0])]=link_allocations0[edge]
    # 为需要重构的通信对寻找最优的电链路
    electric_path_allocations, link_utilization, recon_electric_delay_info = allocate_electric_with_es_optimized(G=topo1, T=T, D=all_to_all_burst_4_dict,
                                                    init_util=existing_utilization0,tor_switches=tor_switches,optical_switches=optical_switches, k_paths=500)
    for pair, path in electric_path_allocations.items():
        print(f"通信对 {pair}: 路径 {'→'.join(path)}")
    for pair, rate in link_utilization.items():
        print(f"链路 {pair}: 当前已分配的流量={rate:.2f} Gbps")
    for pair, delay in recon_electric_delay_info.items():
        status = f"{delay:.2f}s" if delay not in [None, float('inf')] else "超时/未分配"
        print(f"通信对 {pair}: {status}")

    print("输出不需要重构的通信对的通信时间：")
    T_2=[]
    for pair in no_need_recon_pairs0:
        T_2.append(pair)
    comm_time = calculate_communication_times(topo1, all_to_all_burst_4_dict, T_2, paths0)
    for pair, time in comm_time.items():
        print(f"不需要重构的通信对 {pair}: 通信时间={time:.2f} s")

    print("***********输出半更新算法的每个通信对的延迟以及所有通信对的延迟和=======================")
    delays_2={}
    for pair in comm_time:
        if comm_time[pair] is None:
            continue
        else:
            delays_2[pair]=comm_time[pair]
    for pair in recon_electric_delay_info:
        # if pair in delays_2:
        delays_2[pair] = recon_electric_delay_info[pair]
        print(f"通信对{pair}进行了重构")
        print(f"需要重构的通信对 {pair}延迟: {delays_2[pair]}")
        # else:
        #     print(f"通信对{pair}不需要重构,通信时间为原来的")
    total_delays_2=0.0
    max_delays_2=0.0
    for pair in delays_2:
        if delays_2[pair] > max_delays_2:
            max_delays_2 = delays_2[pair]
        print(f"通信对延迟为 {pair}: {delays_2[pair]}")
        total_delays_2 += delays_2[pair]
    print(f"半更新路由算法的最大通信对延迟为 {max_delays_2:.2f}s")
    print(f"半更新路由算法的所有通信对的延迟和为 {total_delays_2:.2f}s")
    return delays_2, total_delays_2,max_delays_2


print("==================固定路由算法（纯走电链路）==================")
def electric_only_algorithm(topo1: nx.Graph, all_to_all_burst_4: dict) -> tuple[dict[Any, Any], float, float | Any]:
    """纯电算法：仅使用电链路传输"""
    all_to_all_burst_4_dict, T2 = maxtri_to_dict(all_to_all_burst_4)
    # 没有突发流量前的通信对的最优路径
    # 有突发流量前的通信对的最优路径
    paths, util, delays = allocate_switches_with_es_optimized(topo1, T2, all_to_all_burst_4_dict, tor_switches,
                                                              optical_switches,
                                                              k_paths=500)
    T_1=[]
    for pair in paths:
        T_1.append(pair)
    # 创建新的初始化字典，完全基于当前拓扑
    util = initialize_utilization(topo1)
    electric_path_allocations, link_utilization, recon_electric_delay_info = allocate_electric_with_es_optimized(G=topo1, T=T_1, D=all_to_all_burst_4_dict,
                                                    init_util=util,tor_switches=tor_switches,optical_switches=optical_switches, k_paths=500)

    for pair, path in electric_path_allocations.items():
        print(f"通信对 {pair}: 路径 {'→'.join(path)}")
    for pair, rate in link_utilization.items():
        print(f"链路 {pair}: 当前已分配的流量={rate:.2f} Gbps")
    for pair, delay in recon_electric_delay_info.items():
        status = f"{delay:.2f}s" if delay not in [None, float('inf')] else "超时/未分配"
        print(f"通信对 {pair}: {status}")

    print("***********输出固定（只走电链路）算法的每个通信对的延迟以及所有通信对的延迟和=======================")
    delays_3={}
    total_delays_3=0.0
    max_delays_3=0.0
    for pair in recon_electric_delay_info:
        if recon_electric_delay_info[pair] is None:
            continue
        else:
            delays_3[pair]=recon_electric_delay_info[pair]
            print(f"通信对 {pair}延迟: {delays_3[pair]}")
    for pair in delays_3:
        if delays_3[pair]>max_delays_3:
            max_delays_3=delays_3[pair]
        # print(f"通信对延迟为 {pair}: {delays_3[pair]}")
        total_delays_3 += delays_3[pair]
    print(f"固定路由算法（纯电链路）的最大通信对延迟为 {max_delays_3:.2f}s")
    print(f"固定路由算法（纯点链路）的所有通信对的延迟和为 {total_delays_3:.2f}s")
    return delays_3, total_delays_3,max_delays_3

print("==================固定路由算法（光电混合链路）==================")
def hybrid_static_algorithm(topo1: nx.Graph, all_to_all_4,all_to_all_burst_4: dict) -> tuple[
    dict[Any, Any], float, float | Any]:
    all_to_all_4_dict, T1 = maxtri_to_dict(all_to_all_4)
    all_to_all_burst_4_dict, T2 = maxtri_to_dict(all_to_all_burst_4)
    # 没有突发流量前的通信对的最优路径
    paths0, util0, delays0 = allocate_switches_with_es_optimized(topo1, T1, all_to_all_4_dict, tor_switches,
                                                                 optical_switches,
                                                                 k_paths=500)
    # 有突发流量前的通信对的最优路径
    paths, util, delays = allocate_switches_with_es_optimized(topo1, T2, all_to_all_burst_4_dict, tor_switches,
                                                              optical_switches,
                                                              k_paths=500)
    """静态混合算法：固定光电路径分配"""
    T_3=[]
    for pair in paths0:
        print(f"通信对 {pair}: 路径 {'→'.join(paths0[pair])}")
        T_3.append(pair)

    communication_times, link_allocations=calculate_communication_metrics(topo1, all_to_all_burst_4_dict, T_3, paths0)
    for pair, time in communication_times.items():
        print(f"通信对 {pair}: 预估延迟={time:.2f}s")

    print(type(link_allocations))
    for pair, path in link_allocations.items():
        print(f"链路 {pair}已经分配的流量为:{link_allocations[pair]} ")

    print("***********输出固定（光电混合链路）算法的每个通信对的延迟以及所有通信对的延迟和=======================")
    delays_4={}
    total_delays_4=0.0
    max_delays_4=0.0
    for pair in communication_times:
        if communication_times[pair] is None:
            continue
        else:
            delays_4[pair]=communication_times[pair]
            print(f"通信对 {pair}延迟: {delays_4[pair]}")
    for pair in delays_4:
        if delays_4[pair] > max_delays_4:
            max_delays_4=delays_4[pair]
        # print(f"通信对延迟为 {pair}: {delays_4[pair]}")
        total_delays_4 += delays_4[pair]
    print(f"固定路由算法（光电混合链路）的最大通信对延迟为 {max_delays_4:.2f}s")
    print(f"固定路由算法（光电混合链路）的所有通信对的延迟和为 {total_delays_4:.2f}s")
    return delays_4, total_delays_4,max_delays_4


def load_traffic_matrix(data, pattern: str, scale: float) -> np.ndarray:
    """加载指定模式的流量矩阵"""
    for entry in data.get(pattern, []):
        if entry.get("scale_factor") == scale:
            return np.array(entry["matrix"])
        elif entry.get("burst_factor") == scale:
            return np.array(entry["matrix"])
    raise ValueError(f"{pattern}中未找到scale_factor={scale}的流量矩阵")

def analyze_algorithms(topo, data):
    """执行全部分析流程"""
    results = {}
    scale=0.0
    for iter in range(10):
        scale=scale+10
        # 加载流量矩阵
        # base_matrix = load_traffic_matrix(data, "all_to_all", scale)
        # burst_matrix = load_traffic_matrix(data, "all_to_all_burst", scale*5)

        base_matrix = load_traffic_matrix(data, "ring_allreduce", scale)
        burst_matrix = load_traffic_matrix(data, "ring_allreduce_burst", scale*5)

        # 运行各算法
        metrics = {
            "full_update": full_update_algorithm(topo, base_matrix, burst_matrix),
            "semi_update": semi_update_algorithm(topo, base_matrix, burst_matrix),
            # "electric_only": electric_only_algorithm(topo, burst_matrix),
            "hybrid_static": hybrid_static_algorithm(topo, base_matrix, burst_matrix)
        }

        # 存储结果
        results[f"scale_{scale}"] = {
            "base_traffic": base_matrix.tolist(),
            "burst_traffic": burst_matrix.tolist(),
            "max_delays": {k: float(v[2]) for k, v in metrics.items()},
            "total_delays": {k: float(v[1]) for k, v in metrics.items()}
            # "delays": {k: v[0].tolist() for k, v in metrics.items()},
            # "total_delays": {k: float(v[1]) for k, v in metrics.items()}
        }

    return results
# def visualize_results(results,PLOT_IMAGE):
#     """可视化延迟对比（横坐标为总流量）"""
#     plt.figure(figsize=(14, 7))
#
#     # 准备数据
#     scale_keys = sorted(results.keys(), key=lambda x: float(x.split('_')[1]))
#     base_traffic_volumes = []
#     traffic_volumes = []
#     for key in scale_keys:
#         # 计算总流量 = 基础流量 + 突发流量
#         base = np.sum(results[key]["base_traffic"])
#         burst = np.sum(results[key]["burst_traffic"])
#         traffic_volumes.append(base + burst)
#         base_traffic_volumes.append(base) # 将总流量设置为基础流量的总流量
#
#     # 算法样式配置
#     algorithms = {
#         "full_update": {"color": "#1f77b4", "label": "全更新算法"},
#         "semi_update": {"color": "#ff7f0e",  "label": "半更新算法"},
#         # "electric_only": {"color": "#2ca02c",  "label": "纯电算法"},
#         "hybrid_static": {"color": "#d62728", "label": "静态混合"}
#     }
#
#     # 绘制曲线
#     for algo, style in algorithms.items():
#         max_delays = [results[key]["max_delays"][algo] for key in scale_keys] # 绘制最大延迟曲线
#         # total_delays = [results[key]["total_delays"][algo] for key in scale_keys] # 绘制总延迟曲线
#         plt.plot(base_traffic_volumes, max_delays,
#                  linewidth=2,
#                  # marker=style["marker"],
#                  markersize=8,
#                  color=style["color"],
#                  label=style["label"])
#
#     # 图表美化
#     plt.title("不同算法延迟随总流量变化趋势", fontsize=14,  fontfamily='SimHei')
#     plt.xlabel("总流量 (GB)", fontsize=12, fontfamily='SimHei')
#     # plt.ylabel("最大延迟 (秒)", fontsize=12, fontfamily='SimHei')
#     plt.ylabel("最大延迟 (秒)", fontsize=12, fontfamily='SimHei')
#
#     # 智能格式化横坐标
#     max_traffic = max(base_traffic_volumes)
#     if max_traffic > 10000:  # 超过10TB用科学计数法
#         plt.ticklabel_format(axis='x', style='sci', scilimits=(0, 0))
#         # plt.xlabel("总流量 (GB) ×10³")
#         plt.xlabel("总流量 (GB) ×1000")
#     else:
#         plt.gca().xaxis.set_major_formatter(plt.FuncFormatter(
#             lambda x, _: f"{x / 1000:.0f}k" if x >= 1000 else f"{x:.0f}"))
#
#     plt.grid(True, alpha=0.3)
#     plt.legend(fontsize=10, loc='upper left')
#     plt.tight_layout()
#
#     # 添加数据标签
#     for x, y in zip(base_traffic_volumes, max_delays):
#         plt.text(x, y, f'{y:.1f}s',
#                  fontsize=8, color=style["color"],
#                  ha='center', va='bottom')
#
#     plt.savefig(PLOT_IMAGE, dpi=300, bbox_inches='tight')
#     plt.show()

def visualize_results(results, PLOT_IMAGE):
    """可视化延迟对比（横坐标为总流量，重复值取首个）"""
    plt.figure(figsize=(14, 7))

    # 数据准备与去重处理
    scale_keys = sorted(results.keys(), key=lambda x: float(x.split('_')[1]))

    seen_traffic = set()  # 用于记录已出现的流量值
    filtered_indices = []  # 保留的数据点索引
    base_traffic_volumes = []

    # 第一次遍历：去重处理
    for idx, key in enumerate(scale_keys):
        traffic = np.sum(results[key]["base_traffic"])  # 使用基础流量作为横坐标
        if traffic not in seen_traffic:
            seen_traffic.add(traffic)
            base_traffic_volumes.append(traffic)
            filtered_indices.append(idx)

    # 算法样式配置
    algorithms = {
        "full_update": {"color": "#1f77b4", "label": "全更新算法"},
        "semi_update": {"color": "#ff7f0e", "label": "半更新算法"},
        "hybrid_static": {"color": "#d62728", "label": "静态混合"}
    }

    # 绘制曲线
    for algo, style in algorithms.items():
        # 从完整数据中筛选去重后的数据点
        max_delays = [results[scale_keys[i]]["max_delays"][algo] for i in filtered_indices]

        plt.plot(
            base_traffic_volumes,
            max_delays,
            linewidth=2,
            marker='o',  # 统一添加圆形标记
            markersize=8,
            color=style["color"],
            label=style["label"]
        )

    # 图表美化
    plt.title("不同算法最大延迟随基础流量变化趋势",
              fontsize=14, fontfamily='SimHei')
    plt.xlabel("allreduce基础流量总量 (GB)", fontsize=12, fontfamily='SimHei')
    plt.ylabel("最大延迟 (秒)", fontsize=12, fontfamily='SimHei')

    # 智能坐标轴格式化
    max_traffic = max(base_traffic_volumes) if base_traffic_volumes else 0
    if max_traffic > 10000:
        plt.gca().xaxis.set_major_formatter(
            plt.FuncFormatter(lambda x, _: f"{x / 1000:.0f}k"))
        plt.xlabel("基础流量总量 (×1000 GB)")
    else:
        plt.gca().xaxis.set_major_formatter(
            plt.FuncFormatter(lambda x, _: f"{int(x)}"))

    plt.grid(True, alpha=0.3)
    plt.legend(fontsize=10, loc='upper left')

    # 添加数据标签（仅显示前3个点示例）
    for algo, style in algorithms.items():
        max_delays = [results[scale_keys[i]]["max_delays"][algo] for i in filtered_indices]
        for x, y in list(zip(base_traffic_volumes, max_delays))[:3]:  # 只标注前3个点
            plt.text(x, y + 0.1, f'{y:.1f}s',
                     fontsize=8, color=style["color"],
                     ha='center', va='bottom')

    plt.tight_layout()
    plt.savefig(PLOT_IMAGE, dpi=300, bbox_inches='tight')
    plt.show()

if __name__ == "__main__":
    # tor_switches = {'ToR1', 'ToR2', 'ToR3', 'ToR4'}
    # optical_switches = {'os1', 'os2', 'os3', 'os4'}
    tor_switches = {'ToR1', 'ToR2', 'ToR3', 'ToR4','ToR5', 'ToR6', 'ToR7', 'ToR8','ToR9', 'ToR10', 'ToR11', 'ToR12','ToR13', 'ToR14', 'ToR15', 'ToR16'}
    optical_switches = {'os1', 'os2', 'os3', 'os4','os5', 'os6', 'os7', 'os8','os9', 'os10', 'os11', 'os12','os13', 'os14', 'os15', 'os16'}
    OUTPUT_JSON = "algorithm_results_allreduce_16_2.json"  # 结果保存路径
    PLOT_IMAGE = "delay_comparison.png"  # 绘图保存路径

    # 调用四个算法
    # delays_1, total_delays_1 = full_update_algorithm(topo1, all_to_all_burst_4_dict)
    # delays_2, total_delays_2 = semi_update_algorithm(topo1, all_to_all_burst_4_dict)
    # delays_3, total_delays_3 = electric_only_algorithm(topo1, all_to_all_burst_4_dict)
    # delays_4, total_delays_4 = hybrid_static_algorithm(topo1, all_to_all_burst_4_dict)
    print("--------------------4节点-----------------------------")
    topo1 = build_hybrid_topology_shared_tor(num_tor=4)
    topo2 = build_hybrid_topology_shared_tor(num_tor=8)
    topo3 = build_hybrid_topology_shared_tor(num_tor=16)

    # 读取流量数据
    with open("traffic_evolution_16.json", 'r') as f:
        traffic_data = json.load(f)
    # 执行分析
    analysis_results = analyze_algorithms(topo3, traffic_data)

    # 保存结果
    with open(OUTPUT_JSON, 'w') as f:
        json.dump(analysis_results, f, indent=2)

    # 可视化
    visualize_results(analysis_results, PLOT_IMAGE)

    # for traffic_matrix in traffic_matrices["all_to_all"]:
    #     if traffic_matrix["scale_factor"] == 1.0:
    #         all_to_all_4 = traffic_matrix["matrix"]
    #         print("all_to_all_4", all_to_all_4)
    #         break
    #     else:
    #         print("没找到目标流量矩阵")
    #
    # for traffic_matrix in traffic_matrices["all_to_all_burst"]:
    #     if traffic_matrix["burst_scale"] == 1.0:
    #         all_to_all_4_burst = traffic_matrix["matrix"]
    #         print("all_to_all_4_burst", all_to_all_4_burst)
    #         break
    #     else:
    #         print("没找到目标流量矩阵")
    #
    # print("=================全更新算法=======================")
    # delays_1,total_delays_1 = full_update_algorithm(topo1, all_to_all_4, all_to_all_4_burst)
    # print("=================半更新算法=======================")
    # delays_2,total_delays_2 = semi_update_algorithm(topo1, all_to_all_4, all_to_all_4_burst)
    # print("=================固定路由（纯电）==================")
    # delays_3,total_delays_3 = electric_only_algorithm(topo1, all_to_all_4_burst)
    # print("====================固定路由（光电混合）====================")
    # delays_4,total_delays_4 = hybrid_static_algorithm(topo1, all_to_all_4, all_to_all_4_burst)



